<template>
  <!-- 总车数:18    上行:场区7,在途6    下行:场区7,在途6    平均速度:上行23km/h,下行 24km/h   -->
  <div class="box_card" ref="boxCard">

    <div class="cardHeader">
      <div class="routeName">{{ routeName }}</div>
      <div class="line_detail">
        <div class="line_margin">总车数:{{ routeStatistics.vehicles }}</div>
        <div class="line_margin">上行:场区{{ routeStatistics.upAreaVehicles }},在途{{ routeStatistics.upVehicles }}</div>
        <div class="line_margin">下行:场区{{ routeStatistics.downAreaVehicles }},在途{{ routeStatistics.downVehicles }}</div>
        <div class="line_margin">
          平均速度:上行{{ routeStatistics.upAvgSpeed }}km/h,
          <span>下行{{ routeStatistics.downAvgSpeed }}km/h</span>
        </div>
        <div class="line_margin">运营:{{ routeStatistics.operationVehicles }}</div>
        <div class="line_margin">非运营:{{ routeStatistics.nonOperationVehicles }}</div>
        <div class="line_margin">
          <el-link type="primary">完成率:{{ routeStatistics.rateExecutedItinerary }}%</el-link>
        </div>
      </div>
      <div class="changeSize">
        <el-switch v-model="isSmall" class="ml-2" inline-prompt
          style="--el-switch-on-color: #13ce66; --el-switch-off-color: #409eff" active-text="小" inactive-text="大" />
      </div>
      <div class="overallShow">
        <span @click="jumpRouteAll">全局显示</span>
      </div>
      <div class="moreBtn">
        <el-tooltip class="box-item" effect="light" placement="bottom-end">
          <template #content>
            <div class="carTooltip">
              <div class="DetailBtn" v-if="!props.isDetailRoute" @click="detailBtn()">线路详情</div>
              <div class="DetailBtn" @click="handlePlayBlack()">直线图回放</div>
              <div class="DetailBtn lastBtn">站点显示</div>
            </div>
          </template>
          <template #default>
            <div class="more_img"></div>
          </template>
        </el-tooltip>
      </div>
    </div>

    <div class="line_main">

      <div class="line_main_left">
        <div class="itxst">
          <div>
            <draggable :list="locationVehicles.up" ghost-class="ghost" chosen-class="chosenClass" animation="300"
              @end="onEnd">
              <template #item="{ element }">
                <div class="item" @contextmenu="showRightMenu($event, element)">
                  <div style="font-size: 12px;" class="left">
                    <span>{{ element.plateNo }} </span>
                    <div class="left_statu">
                      高 6
                    </div>
                  </div>
                  <div class="middle">{{ element.driverName ? element.driverName : '未知' }}</div>
                  <div class="right">{{ element.actualTime }}</div>
                </div>
              </template>

            </draggable>
          </div>
        </div>
      </div>

      <div class="line_main_center">
        <div ref="lineBox" class="line_main_route">
          <!-- 直线图dom -->
          <div :id="'container' + routeId" class="CarStationLineBox" />
          <!-- 直线图上车辆dom -->
          <TeleportContainer v-if="!isMergeRoute" />
        </div>

        <div class="line_main_court">
          <div class="other_location">
            <div>其他场区</div>
            <div class="car-box">
              <div class="other-car" v-for="(item, idx) in locationVehicles.other" :key="idx">{{ item.plateNo }}</div>
            </div>
          </div>
          <!-- 驾驶员信息 -->
          <div class="driver_tip">
            <span class="driver_tip_icon"></span>
            <span>
              驾驶员[{{ locationVehicles.driverName }}]在车辆[{{ locationVehicles.plateNo }}]上签到!({{
                locationVehicles.driverCheckInTime }})</span>
          </div>
        </div>
      </div>


      <div class="line_main_right">
        <div class="plant_table" v-for="item in locationVehicles.down">
          <div style="font-size: 10px;">{{ item.plateNo }}</div>
          <div class="middle">{{ item.driverName ? item.driverName : '未知' }}</div>
          <div>{{ item.actualTime }}</div>
        </div>
      </div>
    </div>

    <playBlack v-if="isPlayBlackShow" v-click-outside="hidePlayBack" @close="hidePlayBack()" />
  </div>
</template>

<script setup>
import { getToken } from '@/utils/auth'
import { result } from 'lodash';
import { onMounted, ref, toRef, watch, reactive } from "vue";
import { Graph } from '@antv/x6';
import "@antv/x6-vue-shape";
import { register, getTeleport } from '@antv/x6-vue-shape';
import { ClickOutside as vClickOutside } from 'element-plus'
import carNode from "./customNodeVue/carNode.vue";
import playBlack from './playback/playback.vue'
import { initRouteData, initEdgeData, initLoopLineNode, initCarNode, initMergeRouteData, moveCar } from './graph/graph.js'
import './customNode/customNode.js';
import draggable from 'vuedraggable'


const router = useRouter();
const { proxy } = getCurrentInstance();


const props = defineProps({
  routeData: Object,   //站点数据
  isPlateNo: Boolean,  //
  index: Number,
  isDetailRoute: Boolean  //是否是详情页
})


// 点击线路详情
const detailBtn = () => {
  router.push({ path: '/smartDispatch/detail', query: { routeId: props.routeData.routeId } })
}
const isPlayBlackShow = ref(false)
const handlePlayBlack = () => {
  isPlayBlackShow.value = true
}
const hidePlayBack = () => {
  isPlayBlackShow.value = false
}


// 注册车辆Car
register({
  shape: 'car_vue_node',
  component: carNode,
})

const isSmall = ref(false)
const isPlateNo = toRef(props, 'isPlateNo')

// 站点线JSON数据
const graphData = ref({
  edges: [],
  nodes: []
})

// 后端线路原始数据
let { routeStatistics, stationList, routeType, operationMode, vehicleList, routeName, routeId } = props.routeData
let isMergeRoute = Object.prototype.toString.call(props.routeData) === '[object Array]'


const locationVehicles = ref({
  up: [],
  down: [],
  other: [],
  going: []
})

vehicleList.forEach((item) => {
  if (item.location == 0) {
    locationVehicles.value.going.push(item)   //行驶中
  } else if (item.location == 1) {
    locationVehicles.value.up.push(item)      //上行
  } else if (item.location == 2) {
    locationVehicles.value.down.push(item)    // 下行
  } else {
    locationVehicles.value.other.push(item)   // 其他车辆
  }
})


// console.log( '这个是进行中的车辆',locationVehicles.value.going);

// 上下行站点数据
const upRouteNode = ref([])
const downRouteNode = ref([])

// 上下行站间线数据
const upEdge = ref([])
const downEdge = ref([])

// 当前线路所有车辆
const vehicleNode = ref([])

// boxRef
const boxCard = ref(null)
const emit = defineEmits(['showCarDialog', 'closeDilog', 'showRightmen', 'closeRightmen', 'showRightmen1'])
const graph = ref(null);

onMounted(() => {
  let TeleportContainer
  // antv自定义节点组件
  if (!isMergeRoute) {
    let componentsArr = []
    for (var i = 1; i < props.index; i++) {
      componentsArr.push(getTeleport())
    }
    TeleportContainer = componentsArr[props.index]
  }

  // 合并线路
  if (isMergeRoute) {
    const { upSubordinateArr, downSubordinateArr, upArr, upLineArr, downArr, downLineArr, downSubordinateLineArr, upSubordinateLineArr } =
      initMergeRouteData(props.routeData[0], proxy.$refs.lineBox.clientWidth, proxy.$refs.lineBox.clientHeight)
    // 站点
    upRouteNode.value = [...upArr]
    downRouteNode.value = [...downArr]
    upSubordinateArr.forEach(item => {
      upRouteNode.value.push(...item)
    })
    downSubordinateArr.forEach(item => {
      downRouteNode.value.push(...item)
    })
    // 主线线条
    upEdge.value = [...upLineArr, ...upSubordinateLineArr]
    downEdge.value = [...downLineArr, ...downSubordinateLineArr]

  } else if (operationMode == 2) {
    /**
    * 直线图demo
    * upStationList, downStationList
    */
    const { upArr, downArr } = initRouteData(stationList, proxy.$refs.lineBox.clientWidth, proxy.$refs.lineBox.clientHeight)
    upRouteNode.value = upArr
    downRouteNode.value = downArr
    // 上下行站间线数据
    const { upLineArr, downLineArr } = initEdgeData(upArr, downArr)
    upEdge.value = upLineArr
    downEdge.value = downLineArr
    vehicleNode.value = initCarNode(vehicleList, upRouteNode.value, downRouteNode.value, isPlateNo.value, isSmall.value, true)

  } else if (operationMode == 1) {
    /**
    * 环线demo
    */
    const { loopLineNode, loopLineEdge } = initLoopLineNode(stationList, proxy.$refs.lineBox.clientWidth, proxy.$refs.lineBox.clientHeight)
    upRouteNode.value = loopLineNode
    upEdge.value = loopLineEdge
    vehicleNode.value = initCarNode(vehicleList, upRouteNode.value, downRouteNode.value, isPlateNo.value, isSmall.value, false, true)
  }


  // 添加node+添加edges
  graphData.value.nodes = [...upRouteNode.value, ...downRouteNode.value, ...vehicleNode.value]
  graphData.value.edges = [...upEdge.value, ...downEdge.value]
  // 渲染函数
  // init window hook
  graph.value = new Graph({
    container: document.getElementById('container' + props.routeData.routeId),
    grid: false,
    width: '100%',
    panning: true,
    background: { color: '#091940' }, //091940
    interacting: () => {
      return {
        nodeMovable: false,
        edgeMovable: false,
        edgeLabelMovable: false
      }
    }
  })
  graph.value.fromJSON(graphData.value)

  setTimeout(() => {
    findAllCars()
  }, 800)


  // 鼠标移入时
  graph.value.on('node:mouseenter', (e) => {
    if (e.node.shape == 'car_vue_node') {

      //没有重合车辆
      if (e.node.data.repeatList.length == 1) {
        emit('showCarDialog', e, true)  //信息弹窗显示
      }
      //有重合车辆
      if (e.node.data.repeatList.length > 1) {
        emit('showCarDialog', e, false)   //信息弹窗不展示
        emit('showRightmen', e, true)
      }

      // emit('showCarDialog', e, true)
    }
  })

  // 鼠标离开时
  graph.value.on('node:mouseout', (e) => {
    if (e.node.shape == 'car_vue_node') {
      emit('closeDilog')
      emit('closeRightmen')
      // emit('showRightmen', e, true) 
    }
  })

  // 右键事件
  graph.value.on('node:contextmenu', (e) => {
    if (e.node.shape == 'car_vue_node') {
      // 没有车标重复
      if (e.node.data.repeatList.length == 1) {
        emit('showRightmen', e, false)
      }
      // 有重复车标
      if (e.node.data.repeatList.length > 1) {
        emit('showRightmen', e, true)
      }
    }
  })

  //webSocket实时更新数据
  let token = encodeURIComponent('Bearer ' + getToken());
  var ws = new WebSocket("ws://192.168.1.209:18080/gissp/dispatch/websocket", [token]);

  ws.onopen = function () {
    const json = JSON.stringify({
      "type": "dispatchDataSubscribe",
      "content": { "routeId": props.routeData.routeId }
    });
    ws.send(json)
    // setInterval(function () {
    //   ws.send("ping");
    // }, 5000);
  };

  ws.onmessage = function (event) {
    let ret = JSON.parse(event.data)

    // console.log('实时更新的消息', ret);

    //  这个是直线图上车辆的实时数据
    if (ret.type == 'dispatchVehicleData') {
      let result = ret.content;
      let moveFlag = moveCar(graph.value, result, props.isPlateNo, isSmall.value)
      if (moveFlag === true) {
        findAllCars()
      }
      //如果当前站为最后一站  加入下行线路
      if (result.location == 0) {
        locationVehicles.value.going.push(result)   //行驶中
      } else if (result.location == 1) {
        locationVehicles.value.up.push(result)      //上行
      } else if (result.location == 2) {
        locationVehicles.value.down.push(result)    // 下行
      } else {
        locationVehicles.value.other.push(result)   // 其他车辆
      }
    }

    //这个是车辆线路信息的实时数据
    if (ret.type == 'dispatchRouteStatistics') {
      routeStatistics = Object.assign(routeStatistics, result)
    }
    // 驾驶员签到信息的实时数据
    // if (ret.type == 'dispatchRouteStatistics') {
    //   routeStatistics = Object.assign(routeStatistics, result)
    // }


  };

  ws.onclose = function () {
    // ws = new WebSocket("ws://example.com");
    // console.log('关闭ws_close')

  };
  ws.onerror = function (e) {
    // console.log('出错ws_error', e)
  }


  // 图例事件
  window.addEventListener('resize', () => {
    // graph.centerContent()
  })
  watch([isPlateNo, isSmall], (newValue, oldValue) => {

    let carNodes = graph.value.getNodes().filter((item) => item.shape == 'car_vue_node');
    carNodes.forEach(node => {
      // const node = graph.getCellById(element)
      //切换的大小更改node的X坐标偏移
      let { x, y } = node.position()
      if (newValue[1] != oldValue[1]) {
        x = newValue[1] ? x + 20 : x - 20;
      }
      node.setData({ ...node.data, isPlateNo: props.isPlateNo, isSmall: isSmall.value })
      node.position(x, y)
    });
  })


})

const Height = ref('200px')
if (isMergeRoute) {
  Height.value = '620px'
}
function findAllCars() {
  let carNodes = graph.value.getNodes().filter((item) => item.shape == 'car_vue_node');
  let positionCarCount = {};
  carNodes.forEach((car) => {
    let { x, y } = car.position()
    let key = x + '-' + y;
    !positionCarCount.hasOwnProperty(key) ? positionCarCount[key] = [] : '';
    positionCarCount[key].push(car.getData())
  })
  Object.keys(positionCarCount).forEach(key => {
    let showCarInfo = positionCarCount[key][0]
    let carNode = graph.value.getCellById(showCarInfo.vehicleId)
    carNode.updateData({ ...carNode.getData(), repeatList: positionCarCount[key] })
    positionCarCount[key].forEach((item, index) => {
      if (index > 0) {
        graph.value.removeNode(item.vehicleId)
      }
    })
  });
}


//拖拽结束的事件
const onEnd = (e) => {
  console.log('变化后的新数组', locationVehicles.value.up);
};

const showRightMenu = (e, item) => {
  console.log('右键了拖拽项', e, item);
  e.preventDefault()
  emit('showRightmen1', e.clientX, e.clientY, item)
  // emit('showRightmen', e, true)
}

//全局显示
const jumpRouteAll = () => {
  router.push('/smartDispatch/routeAll')
}


</script>

<style lang="scss" scoped>
.CarStationLineBox {
  width: 100%;
  height: v-bind(Height);
}

:deep(.x6-node text) {
  // transform: rotate(90deg);
  writing-mode: vertical-lr;
}


:deep(.el-card__body) {
  padding: 0 !important;
}

:deep(.el-divider--horizontal) {
  margin: 0;
  // height: 12em;
}

:deep(.el-divider--vertical) {
  height: 14em;
}

:deep(.el-button+.el-button) {
  margin-left: 0px
}

.carTooltip {
  padding: 0;

  .DetailBtn {
    display: block;
    height: 30px;
    line-height: 30px;
    border-bottom: 1px solid #aaa;
    cursor: pointer;

    &:hover {
      color: #409eff;
    }
  }

  .lastBtn {
    border-bottom: 0px solid transparent !important;
  }
}

.box_card {
  // height: 280px;
  margin-bottom: 10px;
  background-color: #091940;
  display: flex;
  flex-direction: column;

  .cardHeader {
    display: flex;
    padding-right: 20px;
    justify-content: space-between;
    line-height: 40px;
    color: #fff;
    display: flex;
    height: 40px;
    border-bottom: 1px #1b2e5f solid;

    .line_margin {
      margin: 0px 12px;
      font-size: 14px;
    }

    .line_detail {
      flex: 1;
      display: flex;
    }

    .routeName {
      height: 40px;
      border-radius: 0px 10px 0px 0px;
      width: 100px;
      text-align: center;
      color: #fff;
      font-size: 16px;
      font-weight: bold;
      background-color: #668ff5;
      align-items: center;
    }

    .changeSize {
      align-items: center;
      line-height: 40px;

      .middle_btn {
        color: #fff;
        cursor: default;
      }
    }

    .overallShow {
      display: inline-block;
      width: 70px;
      height: 20px;
      background: #668FF5;
      border-radius: 10px;
      text-align: center;
      line-height: 20px;
      margin: 10px 16px 0;
      font-size: 14px;
      padding: 0 4px;
      cursor: pointer;
    }
  }

  .line_main {
    flex: 1;
    display: flex;
    position: relative;

    .line_main_left,
    .line_main_right {
      width: 176px;
      background: #11224b;
      padding: 5px;

      .itxst {
        width: 100%;
        display: flex;

        >div {
          width: 100%;
        }

        .item {
          display: flex;
          justify-content: center;
          align-items: center;
          height: 36px;
          // line-height: 36px;
          font-size: 12px;
          text-align: center;
          color: #aaa;
          background: #1C2F61;
          margin-bottom: 3px;
          border: 1px solid #4E5A75;
          border-radius: 3px;

          .left {
            flex: 3;

            .left_statu {
              color: red;
            }
          }

          .middle {
            flex: 2;
            padding: 10px 0;
            border-right: 1px solid #4E5A75;
            border-left: 1px solid #4E5A75;
          }

          .right {
            flex: 2;
          }
        }

        .item:hover {
          cursor: move;
        }

        .chosenClass {
          background-color: #1b45a7;
        }
      }

    }

    .line_main_center {
      flex: 1;

      .line_main_court {
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: 45px;
        width: 100%;
        padding: 0px 20px;
        color: #fff;
        border-top: 1px solid #1C2F61;

        .other_location {
          display: flex;

          .car-box {
            display: flex;

            .other-car {
              margin-left: 8px;
              color: #9BAFD6;
              font-size: 12px;
              line-height: 20px;
              text-align: center;
              width: 78px;
              height: 20px;
              background: #1C2F61;
              border: 1px solid #4E5A75;
            }
          }
        }

        .driver_tip {
          padding: 0 40px 0 22px;
          border-left: 1px solid #1C2F61;
          vertical-align: middle;
          display: flex;
          align-items: center;

          .driver_tip_icon {
            display: inline-block;
            width: 4px;
            height: 4px;
            background: #668FF5;
            margin-right: 10px;
          }
        }
      }
    }

    .line_main_left {
      border-right: 1px #1C2F61 solid;
    }

    .line_main_right {
      border-left: 1px #1C2F61 solid;
    }
  }
}

.more_img {
  width: 10px;
  margin-top: 10px;
  margin-left: 10px;
  height: 20px;
  cursor: pointer;
  background: url('./customNodeVue/img/more.png') no-repeat;
  background-size: contain;
}
</style>